#include "apue.h"
#include <netdb.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#define MAXSLEEP 128
#define BUFLEN 256

static int clfd= -1;

void print_uptime() {
   int n;
   char buf[BUFLEN];

   while ((n= recv(clfd, buf, BUFLEN, 0)) > 0)
       write(STDOUT_FILENO, buf, n);
   if (n < 0)
       err_sys("recv error");
}

void sigio(int signo) {
   print_uptime();
}

int connect_retry(int domain, int type, int protocol,
        const struct sockaddr *addr, socklen_t alen) {
    int numsec;

    for (numsec=1; numsec<= MAXSLEEP; numsec *= 2) {
        if ((clfd= socket(domain, type, protocol)) < 0) {
            return -1;
        }
        if (fcntl(clfd, F_SETOWN, getpid()) < 0) {
            err_sys("F_SETOWN error");
            close(clfd);
            return -1;
        }
        int flag= 1;
        if (ioctl(clfd, FIOASYNC, &flag) < 0) {
            err_sys("FIOASYNC error");
            close(clfd);
            return -1;
        }

        if ((connect(clfd, addr, alen)) < 0) {
            if (errno == EINTR) {
                return clfd; 
            } else 
                continue;
        }
        return clfd;

    }
    return -1;
}

int main(int argc, char *argv[]) {
    struct sockaddr_in addr;
    int err;

    struct sigaction sigact;
    sigact.sa_handler= sigio;
    sigact.sa_flags= 0;
    sigemptyset(&sigact.sa_mask);
    if (sigaction(SIGIO, &sigact, NULL) < 0)
        err_sys("signal error");
    
    memset(&addr, 0, sizeof(addr));
    addr.sin_family= AF_INET;
    addr.sin_port= htons(8080);
    if ((addr.sin_addr.s_addr= inet_addr("127.0.0.1")) == INADDR_NONE) {
        err_sys("address is invalid");
    }
    if ((connect_retry(AF_INET, SOCK_STREAM, 0,(const struct sockaddr *)&addr, sizeof(addr))) < 0)
        err= errno;
    else {
        exit(0);
    }
    err_exit(err, "cant connet to 127.0.0.1");
}
